/*******************************************************************************
 * @file Copyright 2009 The CREATE Lab at CMU
 * 
 *       This file is part of JubJub, an open source project.
 *       http://code.google.com/p/jubjub/
 * 
 *       Redistribution and use in source and binary forms, with or without
 *       modification, are permitted provided that the following conditions are
 *       met:
 * 
 *       Redistributions of source code must retain the above copyright notice,
 *       this list of conditions and the following disclaimer.
 * 
 *       Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 * 
 *       Neither the name of Carnegie Mellon nor the names of its contributors
 *       may be used to endorse or promote products derived from this software
 *       without specific prior written permission.
 * 
 *       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *       "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *       LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 *       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *       HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *       SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *       LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *       DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *       THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *       (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *       OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *******************************************************************************/

package edu.cmu.ri.createlab.jj.blocks;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import edu.cmu.ri.createlab.jj.JubJub.EmptyStringException;
import edu.cmu.ri.createlab.jj.blocks.BlockDefs.BlockTypes;
import edu.cmu.ri.createlab.jj.projects.JJClass;
import edu.cmu.ri.createlab.jj.visitors.BVReturn;
import edu.cmu.ri.createlab.jj.visitors.BlockVisitorInterface;

/**
 * 
 * @author Erik Pasternak
 *
 * CommentBlock allows comments to be added inline with code.
 * 
 * CommentBlock is a direct implementation of the BlockInterface. Since
 * it only allows comments to be added inline with code no information is
 * needed beyond the default BlockInterface definitions.
 */
public class CommentBlock implements BlockInterface
{
   
   /**
    * \defgroup BlockVars These variables are common to all BlockInterface types.
    */
   /*@{*/

   ///The name given to this block. CodeBlock and BlockBlock types should have unique names
   private String name;
   ///The JJClass which these blocks belong to and where they will be written to
   ///when output as code/xml
   private JJClass classOwner;
   ///What type of block this is from the list of BlockTypes
   private BlockTypes type;
   ///A unique ID for this block
   private int id;
   ///A list of RefBlock instances that reference this block.
   private List<RefBlock> refs;
   ///Whether this block is still valid or not
   private boolean valid;
   ///comment for this block
   private String comment;
   
   
   /*@}*/
   
   public CommentBlock(String name, JJClass owner, int ID)
   {
      this.name = name;
      this.classOwner = owner;
      this.id = ID;
      this.type = BlockTypes.COMMENT;
      this.refs = new LinkedList<RefBlock>();
      this.valid = true;
      this.comment = "";
   }
   
   public CommentBlock clone(int ID)
   {
      CommentBlock tempBlock = new CommentBlock(name, classOwner, ID);
      tempBlock.setComment(comment);
      return tempBlock;
   }
   
   /**
    * \defgroup BlockMethods These methods are common to all blocks.
    */
   /*@{*/

   ///Sets the comment for this block
   public void setComment(String comment)
   {
      this.comment = comment;
   }
   ///Gets the comment for this block
   public String getComment()
   {
      return comment;
   }
   
   ///Return whether this block is still valid or if it is deleted pending
   ///removal of all its refs.
   public boolean isValid()
   {
      return valid;
   }
   
   ///Sets this block to not Valid and updates all its refs
   public void deleteBlock()
   {
      valid = false;
      this.updateRefs();
   }
   
   ///Sets this block to Valid and updates all its refs
   public void undeleteBlock()
   {
      valid = true;
      this.updateRefs();
   }
   
   ///Accepts a BlockVisitorInterface and visits itself
   public BVReturn accept(BlockVisitorInterface bv)
   {
      bv.visit(this);
      return null;
   }
   
   ///returns the JJClass that owns this block
   
   public JJClass getOwner()
   {
      return classOwner;
   }

   ///returns the id for this block
   
   public int getID()
   {
      return id;
   }

   ///returns the name of this block
   
   public String getName()
   {
      return name;
   }

   ///returns the BlockTypes type of this block
   
   public BlockTypes getType()
   {
      return type;
   }
   
   ///CommentBlock doesn't own any references so it never has an error
   ///The RefBlock referencing this block might have an error, but that
   ///doesn't matter to the CommentBlock.
   public boolean hasError()
   {
      return false;
   }
   
   ///Since it owns no refs it doesn't have anything to check for errors
   public void checkError()
   {
      return;
   }
   
   ///This makes it easier for the garbage collector to remove this block
   ///by ensuring all the references it contains are removed.
   public void destroyBlock()
   {
      ///Comment blocks are accessible through a single reference block, which
      ///if it is removed essentially destroys the comment block.
      ///In case this changes in the future this code is still included.
      Iterator<RefBlock> it = this.refs.iterator();
      while(it.hasNext())
         it.next().clearBlock();
      this.refs.clear();
   }

   ///sets the JJClass that owns this block
   
   public void setOwner(JJClass owner)
   {
      this.classOwner = owner;
      
   }

   ///sets the name of this block as well as its callName.
   
   public void setName(String name) throws EmptyStringException
   {
      ///If the name is of 0 length we've made a mistake and need to throw
      ///an exception.
      if(name.length() == 0) 
      {
         throw new EmptyStringException("Empty string name");
      }
      this.name = name;
   }
   
   ///Adds a RefBlock to the list of references
   
   public void addRef(RefBlock ref)
   {
      if(refs.contains(ref)) return;
      refs.add(ref);
   }

   ///Removes the given RefBlock from the list of references
   
   public void remRef(RefBlock ref)
   {
      refs.remove(ref);
   }
   
   ///Returns a list of RefBlock types that reference this block
   public List<RefBlock> getRefs()
   {
      return refs;
   }

   ///Updates all the RefBlock references to this block
   
   public void updateRefs()
   {
      Iterator<RefBlock> it = refs.iterator();
      while(it.hasNext())
      {
         it.next().update();
      }
   }
   
   /*@}*/

}
